import json

import math
from flask import Flask, render_template, request, jsonify
import requests
import os
import threading

# 实例化flask
app = Flask(__name__)

# IMDb网站申请的 api key
api_key = 'k_z816w9tz'

# 请求头
header = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.115 Safari/537.36"
}

"""
所使用的API以及功能:

1.top250的电影
https://imdb-api.com/en/API/Top250Movies/{api_key}

2.最受欢迎的电影
https://imdb-api.com/zh/API/MostPopularMovies/{api_key}

3.获取电影海报数据，选取一张海报 下载缓存到本地
https://imdb-api.com/zh/API/Posters/{api_key}/{id}

4.即将上映
https://imdb-api.com/en/API/ComingSoon/{api_key}

5.搜索电影
https://imdb-api.com/API/AdvancedSearch/{api_key}?title=xxx

6.获取一部电影的部分信息
https://imdb-api.com/zh/API/Title/{api_key}/{id}/FullActor,FullCast,Posters,Images,


"""


@app.route('/')  # 返回首页面
def index():
    return render_template("index.html")


@app.route('/search')  # 返回搜索页面
def search():
    search_value = request.args.get("search_value")
    return render_template("search.html", search_value=search_value)


@app.route('/detail/<string:id>')  # 电影的详细
def detail(id):
    url = "https://imdb-api.com/zh/API/Title/{api_key}/{id}/FullActor,FullCast,Posters,Images".format(api_key=api_key,
                                                                                                      id=id)
    response = requests.get(url)
    data = response.json()
    data = json.dumps(data)  # 这里json 字符串
    return render_template("detail.html", data=data)


# 获取最受欢迎电影数据，前端滑动展示
@app.route("/posters")
def get_InTheaters():
    # 构造最受欢迎电影api
    MostPopularMovies_API = "https://imdb-api.com/en/API/MostPopularMovies/{}".format(api_key)
    # 通过requests get 方法获取最受欢迎数据
    data = requests.get(MostPopularMovies_API, headers=header)
    # api 返回的是json 格式数据，直接使用json 获取
    data = data.json()
    # 由于数据里返回的图片是一张小图，这里利用 下载海报api 下载海报用于前端宣传展示
    # imdb 网站比较慢为了加速我们的网站访问速度，对图片进行缓存
    result = []
    url_root = request.url_root
    load_image(data, result, url_root)
    return jsonify(result)


def load_image(data, result, url_root):
    # data: 最受欢迎电影数据
    # 返回 : 包含下载好的海报链接的字典数据

    items = data.get("items")[:16]  # 值取前16个最受欢迎的
    # 利用多线程，加速获取到海报
    thread_task = []
    for i in items:
        t = threading.Thread(target=task_load, args=(i, result, url_root))  # 启用多线程下载
        t.start()
        thread_task.append(t)
    for i in thread_task:
        i.join()  # 等待下载海报的线程结束


# 下载函数
def task_load(data, result, url_root):
    # 下载图片之前先查询本地是否又缓存，如果有则不下载
    # 下载的海报保存到 static/media/image目录
    base_path = "./static/media/image"
    # 获取到图片链接
    id = data.get("id")
    if not id:
        return
    # 查询目录是否存在 ，不存在则创建
    if not os.path.isdir(base_path):
        os.makedirs(base_path)
    # 获取到图片的名称
    image_name = "{}.jpg".format(id)
    # 如果海报已经下载，则构造本地url ，不继续下载海报
    if image_name in os.listdir(base_path):
        url = url_root + os.path.join(base_path, image_name)
        data["posters"] = url
        result.append(data)
        return
    else:
        # 请求获取海报数据
        posters_url = "https://imdb-api.com/zh/API/Posters/{api_key}/{id}".format(api_key=api_key, id=id)
        response = requests.get(posters_url, headers=header)
        posters = response.json()
        posters = posters.get("posters")
        link = None
        # 图片太大，这里尽量获取一张小图
        posters = sorted(posters, key=lambda r: (r['height'], r['width']))
        if len(posters) > 0:  # 取高度最小的一张图片
            link = posters[0]["link"]
        if not link:
            return
        path = os.path.join(base_path, image_name)
        if write_image(link, path):
            url = url_root + os.path.join(base_path, image_name)
            data["posters"] = url
            result.append(data)
            return


# 下载网络图片到本地
def write_image(link, path):
    r = requests.get(link)
    # 判断响应状态
    if r.status_code == 200:
        # 创建文件保存图片
        with open(path, 'wb') as f:
            # 将图片字节码写入创建的文件中
            f.write(r.content)
        return True


def filter_image(data):
    if data.get("height") < 900 and data.get("width") > 1000:
        return data
    return False


# 获取top250的电影信息，然后进行分页，返回
@app.route("/get_top250")
def get_top250():
    url = "https://imdb-api.com/en/API/Top250Movies/{}".format(api_key)
    response = requests.get(url)  # 请求api 获取top 250数据
    data = response.json()
    items = data.get("items")
    page = request.args.get("page")
    pagesize = 8
    if not page:
        return jsonify({"data": [], "total_page": 0, "cur_page": 0})
    # 调用分页函数
    data, cur_page, total_page = page_process(items, pagesize, page)

    return jsonify({"total_page": total_page, "cur_page": cur_page, "data": data})


# 获取最受欢的电影信息，然后进行分页，返回
@app.route("/get_MostPopularData")
def get_MostPopularData():
    url = "https://imdb-api.com/en/API/MostPopularMovies/{}".format(api_key)
    response = requests.get(url)  # 请求api 获取top 250数据
    data = response.json()
    items = data.get("items")
    page = request.args.get("page")
    pagesize = 8
    if not page:
        return jsonify({"data": [], "total_page": 0, "cur_page": 0})
    # 调用分页函数
    data, cur_page, total_page = page_process(items, pagesize, page, False)
    return jsonify({"total_page": total_page, "cur_page": cur_page, "data": data})


# 获取最受欢的电影信息，然后进行分页，返回
@app.route("/get_ComingSoon")
def get_ComingSoon():
    url = "https://imdb-api.com/en/API/ComingSoon/{}".format(api_key)
    response = requests.get(url)  # 请求api 获取top 250数据
    data = response.json()
    items = data.get("items")
    page = request.args.get("page")
    pagesize = 8
    if not page:
        return jsonify({"data": [], "total_page": 0, "cur_page": 0})
    # 调用分页函数
    data, cur_page, total_page = page_process(items, pagesize, page, False)
    return jsonify({"total_page": total_page, "cur_page": cur_page, "data": data})


# 对数据进行分页
def page_process(items, pagesize, page, img_skip=True):
    # 对数据进行分页
    page = int(page)
    page = 1 if page <= 0 else page
    total_page = math.ceil(len(items) / pagesize)
    if page > total_page:
        page = total_page
    cur_page = page
    result = items[(page - 1) * pagesize:page * pagesize]
    if img_skip:
        s = []
        for i in result:  # 将图片替换成小图，加载快点。
            image = i.pop('image')
            i["image"] = image.replace("original", "384x450")  # 如果存在则替换 ,最受欢迎的api 返回的图片不一样，注意
            s.append(i)
    else:
        s = result
    return s, cur_page, total_page


@app.route("/search_data")
def get_search():
    title = request.args.get("title")
    url = "https://imdb-api.com/API/AdvancedSearch/{}?title={}".format(api_key, title)
    response = requests.get(url)
    data = response.json()
    results = data.get("results")
    if results:
        s = []
        for i in results:  # 将图片替换成小图，加载快点。
            image = i.pop('image')
            i["image"] = image.replace("original", "384x450")  # 如果存在则替换
            s.append(i)
        data["results"] = s
    return jsonify(data)


if __name__ == "__main__":
    print(app.url_map)
    # 启动服务器，监听本机IP，端口使用9090 ,debug 模式
    app.run("0.0.0.0", port=9999, debug=True)
